package ch.unifr.diva.multimodals.spherex;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;

public class IpSetter extends Activity {
	public static final String NEW_IP = "NEW_IP";
	public static final String NEW_PORT = "NEW_PORT";

	private EditText ip1, ip2, ip3, ip4, port;
	private Button test, save, cancel;
	private SpinningState myRunnable;
	private Handler h;
	private ImageView connectionStatus;
	private MultimodalDialog md;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.ip_configuration);

		
		//Feedback class
		md= new MultimodalDialog(this);
		
		
		//Initialize buttons and views
		ip1 = (EditText) findViewById(R.id.ipAddress1);
		ip1.setText(R.string.initialIpAddress1);
		ip2 = (EditText) findViewById(R.id.ipAddress2);
		ip2.setText(R.string.initialIpAddress2);
		ip3 = (EditText) findViewById(R.id.ipAddress3);
		ip3.setText(R.string.initialIpAddress3);
		ip4 = (EditText) findViewById(R.id.ipAddress4);
		ip4.setText(R.string.initialIpAddress4);
		port = (EditText) findViewById(R.id.port);
		port.setText(R.string.initialPort);

		test = (Button) findViewById(R.id.ipAddress_testButton);
		save = (Button) findViewById(R.id.ipAddress_saveButton);
		save.setEnabled(false);
		cancel = (Button) findViewById(R.id.ipAddress_cancelButton);

		connectionStatus = (ImageView) findViewById(R.id.ipAddress_imageView);
		
		
		
		//Set status to 'disconnected' at the beginning
		connectionStatus.setImageDrawable((Drawable) getResources()
				.getDrawable(android.R.drawable.presence_busy));
		

		//Initialize turning progress bar
		h = new Handler();
		myRunnable = new SpinningState();
		

		//Initialize test procedure
		test.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				myRunnable.start();
				new ConnectionTester().execute(IpSetter.this);
			};

		});

		//Initialize save procedure
		save.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				Intent intent = new Intent(getApplicationContext(), NetConfigurationActivity.class);
				intent.putExtra(NEW_IP, getIp());
				intent.putExtra(NEW_PORT, getPort());
				setResult(RESULT_OK, intent);
				finish();
			}
		});
		//Initialize cancel procedure
		cancel.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				Intent intent = new Intent(getBaseContext(),
						NetConfigurationActivity.class);
				setResult(RESULT_CANCELED, intent);
				finish();
			}
		});

	}

	
	/**
	 * Shortcut for calling the feedback dialog to give feedbacks 
	 * @param positiveAnswer Whether action was completed successfully or not
	 * @param playSound Whether or not a sound should be played
	 */
public void confirm(boolean positiveAnswer, boolean playSound){
	md.confirm(positiveAnswer, playSound);
}


/**
 * 
 * @return The IP address from the text fields
 */
	public String getIp() {
		return ip1.getText().toString() + "." + ip2.getText().toString() + "."
				+ ip3.getText().toString() + "." + ip4.getText().toString();
	}

	/**
	 * 
	 * @return The port from the text field
	 */
	public int getPort() {
		return Integer.parseInt(port.getText().toString());
	}
	
	
	
	/**
	 * Auxiliary method to display a "busy wheel" while an action is taking place
	 * @author Dani
	 *
	 */
	public class SpinningState implements Runnable{
		ProgressBar progressBar;

		/**
		 * Constructor
		 */
		SpinningState(){
			progressBar=(ProgressBar) findViewById(R.id.ipAddress_testing);;
			progressBar.setVisibility(ProgressBar.INVISIBLE);
		}
		
		boolean done=true;
		public void run() {
			if (!done) {
				progressBar.incrementProgressBy(1);
				progressBar.invalidate();
				h.postDelayed(myRunnable, 10); // run again after 10 ms
			}
		}
		/**
		 * Make the wheel turn
		 */
		public void start(){
			done=false;
			progressBar.setVisibility(ProgressBar.VISIBLE);
			run();
			h.postDelayed(myRunnable, 10);
		}
		/**
		 * Stop the wheel
		 */
		public void stop(){
			progressBar.getHandler().post(new Runnable() {
				public void run() {
					progressBar.setVisibility(View.INVISIBLE);
				}
			});
			done=true;
			h.removeCallbacks(myRunnable);
		}
		
		
	}
	
	/**
	 * Separate thread to test the connection to the main application
	 * @author Dani
	 *
	 */
	public static class ConnectionTester extends AsyncTask<IpSetter, Integer, Boolean>{
	private IpSetter is;
	protected Runner.Reason reason;
	@SuppressWarnings("unused")
	private MultimodalDialog md;
		
	/**
	 * Actually performing the action
	 */
	@Override
	protected Boolean doInBackground(IpSetter... params) {
		this.is=params[0];
		ConnectivityManager cm = (ConnectivityManager) params[0]
				.getSystemService(Context.CONNECTIVITY_SERVICE);

		//Do only continue if wireless connection is active
		if (cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
				.isConnectedOrConnecting()
				|| cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
						.isConnectedOrConnecting()) {
			Socket socket = null;
			OutputStream out=null;
			PrintWriter output=null;
			try {
				socket = new Socket(params[0].getIp(), params[0].getPort());
				out = socket.getOutputStream();
			    output = new PrintWriter(out);
			    //Send test string to main application
				output.print(is.getString(R.string.status_checkConnection));
			    output.flush();
			    output.close();
			    return true;
//				if(socket.isConnected())
//					return true;
//				else{
//					reason=Runner.Reason.SOCKET_NOT_CONNECTED;
//					return false;
//				}
				
			} catch (UnknownHostException e) {
				reason=Runner.Reason.UNKNOWN_HOST;
				return false;
			} catch (IOException e) {
				reason=Runner.Reason.IOEXCEPTION;
				return false;
			} finally {
				//Close open socket and writer
				if (socket!=null && !socket.isClosed())
					try {
						socket.close();
						output.close();
						out.close();
					} catch (IOException e) {
					}
			}
		} else {
			reason=Runner.Reason.NO_INTERNET_CONNECTION;
			return false;
		}
	}
	
	/**
	 * If connection has been checked, proceed with result gotten
	 */
	@Override
	protected void onPostExecute(Boolean result) {
	if(result){
		is.confirm(true, false);
		is.save.setEnabled(true);
		is.connectionStatus.setImageDrawable((Drawable) is.getResources()
				.getDrawable(android.R.drawable.presence_online));
	} else {
		//Inform the user and set connection state accordingly
		is.confirm(false, true);
		String rs=null;
		switch(reason){
		case NO_INTERNET_CONNECTION:
			rs=is.getString(R.string.status_noInternetConnection);
			break;
		case SOCKET_NOT_CONNECTED:
			rs=is.getString(R.string.status_socketNotConnected);
			break;
		case IOEXCEPTION:
			rs=is.getString(R.string.status_ioException);
			break;
		case UNKNOWN_HOST:
			rs=is.getString(R.string.status_unknownHost);
			break;
		case UNKNOWN:
		default:
			rs=is.getString(R.string.status_reasonUnknown);
		break;
		}
		//Inform the user and set connection state accordingly
		Toast.makeText(is.getApplicationContext(), is.getString(R.string.status_noConnectionAvailable)+rs,
				Toast.LENGTH_LONG).show();
		is.save.setEnabled(false);
		is.connectionStatus.setImageDrawable((Drawable) is.getResources()
				.getDrawable(android.R.drawable.presence_busy));
	}
	//Stop turning wheel
	is.myRunnable.stop();
	}
	
}
	
}
